﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;

namespace VehicleWeaponsMod
{
    public class VehicleWeapon
    {
        private uint timesinceshot = 0;
        public int WeaponCount = 2;
        private ArrayList _WeaponPeds; // the hidden peds that actualy hold the weapons
        private ArrayList _WeaponObjects; // the object that attaches to car, just for looks
        private GTA.GameObject _WeaponTarget; // the hidden target that the ped will be shooting at
        public GTA.eWeapon WeaponType = GTA.eWeapon.WEAPON_MP5;
        public GTA.Vehicle WeaponVehicle; // vehicle that weapon is attached to 
        public GTA.eModel WeaponModel = GTA.eModel.MODEL_CJ_PROP_MP5;
        public bool IsTargeted = false; // does aim with camera
        public eAttachPoint AttachPoint = eAttachPoint.Front_Bumper;
        public enum eAttachPoint
        {
            Front_Bumper,
            Back_Bumper,
            Roof
        }
        private eMode Mode = eMode.Idle;
        public enum eMode
        {
            Idle,
            Attaching,
            Active
        }

        public bool isAttached
        {
            get
            {
                if (Mode != eMode.Active) return false;
                if (!GTA.Vehicle.Exists(WeaponVehicle)) return false;
                foreach (GTA.Ped wepped in _WeaponPeds)
                {
                    if (!GTA.Ped.Exists(wepped)) return false;
                }
                if (!GTA.GameObject.Exists(_WeaponTarget)) return false;
                return true;
            }
        }

        public bool isAttachedToCurrentVehicle
        {
            get
            {
                if (!isAttached) return false;
                GTA.Player pl = new GTA.Player();
                GTA.Vehicle plv = pl.GetPlayerPed().GetVehiclePedIsDriving();
                if (!GTA.Vehicle.Exists(plv)) return false;
                if (plv.Handle != WeaponVehicle.Handle) return false;
                return true;
            }
        }

        public VehicleWeapon()
        {
            _WeaponPeds = new ArrayList();
            _WeaponObjects = new ArrayList();

            GTA.Events.RunTick.Handler += Tick;
        }

        unsafe public bool AttachToVehicle(GTA.Vehicle vehicle)
        {
            if (isAttached) { Log.Debug("Already Attached"); Detach(); }
            if (!GTA.Vehicle.Exists(vehicle)) return false;
            WeaponVehicle = vehicle;
            Mode = eMode.Attaching;
            Mode = eMode.Attaching;
            // -- request the models
            GTA.ScriptApi.RequestModel(GTA.eModel.MODEL_M_Y_TOUGH_05);
            GTA.ScriptApi.RequestModel(WeaponModel);
            GTA.ScriptApi.RequestModel(GTA.eModel.MODEL_CJ_WASH_MAC_4);
            if (!GTA.ScriptApi.HasModelLoaded(GTA.eModel.MODEL_M_Y_TOUGH_05)) { return false; }
            if (!GTA.ScriptApi.HasModelLoaded(WeaponModel)) { return false; }
            if (!GTA.ScriptApi.HasModelLoaded(GTA.eModel.MODEL_CJ_WASH_MAC_4)) { return false; }
            // ---------------

            GTA.Vector3 pos = vehicle.Coordinates;
            pos.X -= 20.0F;
            for (int i = 0; i < WeaponCount; i++)
            {
                GTA.Ped wepped = GTA.World.CreatePed(GTA.eModel.MODEL_M_Y_TOUGH_05, pos);
                if (!GTA.Ped.Exists(wepped)) { Log.Error("create wepped failed."); _WeaponPeds.Clear(); _WeaponObjects.Clear(); return false; }
                _WeaponPeds.Add(wepped);
            }

            pos.Y -= 20.0F;
            _WeaponTarget = GTA.World.CreateObject(GTA.eModel.MODEL_CJ_WASH_MAC_4, pos);
            if (!GTA.GameObject.Exists(_WeaponTarget)) { Log.Error("create weptarget failed."); _WeaponPeds.Clear(); return false; }
            GTA.ScriptApi.SetObjectVisible(_WeaponTarget, false);
            GTA.ScriptApi.SetObjectCollision(_WeaponTarget, false);

            if (AttachPoint == eAttachPoint.Roof) IsTargeted = true; // DEBUG
            if (IsTargeted)
            {
                 GTA.ScriptApi.AttachObjectToPed(_WeaponTarget, (GTA.Ped)_WeaponPeds[(int)(uint)(WeaponCount/2)],GTA.ePedBone.unk0, 0.0F, 70.0F, -1.0F, 0.0F, 0.0F, 0.0F,0);
            }
            else if (AttachPoint == eAttachPoint.Back_Bumper)
            {
                GTA.ScriptApi.AttachObjectToCar(_WeaponTarget, WeaponVehicle, 0, 0.0F, -70.0F, 2.0F, 0.0F, 0.0F, 0.0F);
            }
            else // front or roof, not targetted
            {
                GTA.ScriptApi.AttachObjectToCar(_WeaponTarget, WeaponVehicle, 0, 0.0F, 70.0F, 2.0F, 0.0F, 0.0F, 0.0F);
            }
            
            float f=0.0F;
            foreach (GTA.Ped wepped in _WeaponPeds)
            {
                GTA.GameObject wepobj = GTA.World.CreateObject(WeaponModel, pos);
                if (!GTA.GameObject.Exists(wepobj)) { Log.Error("create wepobj failed."); _WeaponObjects.Clear(); _WeaponPeds.Clear(); return false; }
                _WeaponObjects.Add(wepobj);

                GTA.ScriptApi.SetCharCollision(wepped, false);
                GTA.ScriptApi.SetCharProofs(wepped, true, true, true, true, true);
                GTA.ScriptApi.GiveWeaponToChar(wepped, WeaponType, 9999, false);
                GTA.ScriptApi.SetCurrentCharWeapon(wepped, WeaponType, true);
                GTA.ScriptApi.SetCharAccuracy(wepped, 90);
                GTA.ScriptApi.SetCharVisible(wepped, false);

                GTA.ScriptApi.SetCharNeverTargetted(wepped, true); // not needed
                GTA.ScriptApi.AllowReactionAnims(wepped, false); // not needed
                GTA.ScriptApi.SetCharRelationshipGroup(wepped, 0); // not needed
                //GTA.ScriptApi.SwitchPedToAnimated(wepped, false);// not needed

                GTA.DecisionMaker dmfreeze = new GTA.DecisionMaker();// not needed
                GTA.ScriptApi.LoadCombatDecisionMaker(0, dmfreeze);// not needed
                GTA.ScriptApi.SetCombatDecisionMaker(wepped, dmfreeze);// not needed
                dmfreeze = new GTA.DecisionMaker();// not needed
                GTA.ScriptApi.LoadCharDecisionMaker(0, dmfreeze);// not needed
                GTA.ScriptApi.SetCharDecisionMaker(wepped, dmfreeze);// not needed


                // pos
                float fi = f;
                if ((WeaponCount % 2) == 0) fi += 0.5F; // even
                float xpos = (float)(fi - (WeaponCount / 2));
                xpos *= (1.5F / WeaponCount);
                f += 1.0F; // for next loop
                // /pos
                if (AttachPoint == eAttachPoint.Front_Bumper)
                {
                    GTA.ScriptApi.AttachPedToCar(wepped, WeaponVehicle, 0, xpos, 3.0F, -0.5F, 0.0F, WeaponVehicle.Heading, 0, 0);
                    GTA.ScriptApi.AttachObjectToCar(wepobj, WeaponVehicle, 0, xpos, 2.3F, 0.0F, 0.0F, 0.0F, 1.6F);
                    wepped.Heading = WeaponVehicle.Heading;
                }
                else if (AttachPoint == eAttachPoint.Roof)
                {
                    GTA.ScriptApi.AttachPedToCar(wepped, WeaponVehicle, 0, xpos, 0.0F, 0.3F, 0.0F, WeaponVehicle.Heading, 0, 0);
                    GTA.ScriptApi.AttachObjectToCar(wepobj, WeaponVehicle, 0, xpos, -0.2F, 0.7F, 0.0F, 0.0F, 1.6F);
                    wepped.Heading = WeaponVehicle.Heading;
                }
                else if (AttachPoint == eAttachPoint.Back_Bumper)
                {
                    GTA.ScriptApi.AttachPedToCar(wepped, WeaponVehicle, 0, xpos, -3.0F, -0.5F, 0.0F, WeaponVehicle.Heading, 0, 0);
                    GTA.ScriptApi.AttachObjectToCar(wepobj, WeaponVehicle, 0, xpos, -2.3F, 0.0F, 0.0F, 0.0F, -1.6F); 
                    wepped.Heading = WeaponVehicle.Heading-180.0F;
                }

                if (IsTargeted)
                {
                    GTA.Camera gamecam = new GTA.Camera();
                    GTA.ScriptApi.GetGameCam(gamecam);
                    float rotx, roty, rotz;
                    GTA.ScriptApi.GetCamRot(gamecam, &rotx, &roty, &rotz);
                    wepped.Heading = rotz;
                }   
            }
            Mode = eMode.Active;
            Log.Message("Vehicle Weapons Attached: " + WeaponType.ToString());
            return true;
        }

        unsafe public void Tick(Object sender, EventArgs args)
        {
            if (Mode == eMode.Attaching)
            { // keep trying to attach untill succeeds
                AttachToVehicle(WeaponVehicle);
            }
           // Log.Debug("Tick not attaching check");
            if (!isAttached) return;

            GTA.Vector3 target = _WeaponTarget.Coordinates;
            foreach (GTA.Ped wepped in _WeaponPeds)
            {
                if (timesinceshot > 1) GTA.ScriptApi.TaskAimGunAtCoord(wepped, target.X, target.Y, target.Z, 1200000); // this is the only way i could stop them from having a mind of their own, someone please tell me the proper way to do this
                GTA.ScriptApi.ClearCharLastDamageEntity(wepped); // test, not needed

                if (IsTargeted)
                {
                    GTA.Camera gamecam = new GTA.Camera();
                    GTA.ScriptApi.GetGameCam(gamecam);
                    float rotx, roty, rotz;
                    GTA.ScriptApi.GetCamRot(gamecam, &rotx, &roty, &rotz);
                    GTA.ScriptApi.SetCharHeading(wepped, rotz);

                    // now set the weapons heading
                    foreach (GTA.GameObject wepobj in _WeaponObjects)
                    {
                        if (!GTA.GameObject.Exists(wepobj)) continue;
                        GTA.Quaternion newquat = wepobj.Coordinates.GetRotationTo(GTA.World.GetAimCoordinates(70.0F));
                        //wepobj.Quaternion = newquat;
                    }

                }
                else if (AttachPoint == eAttachPoint.Front_Bumper)
                {
                    wepped.Heading = WeaponVehicle.Heading;
                }
                else if (AttachPoint == eAttachPoint.Back_Bumper)
                {
                    wepped.Heading = WeaponVehicle.Heading - 180.0F;
                }
                else if (AttachPoint == eAttachPoint.Roof)
                {
                    wepped.Heading = WeaponVehicle.Heading;
                }
            }

            timesinceshot++;
        }

        unsafe public bool FireWeapon()
        {
            if (!isAttached) return false;
            GTA.Vector3 target = _WeaponTarget.Coordinates;
            timesinceshot = 0;

            foreach (GTA.Ped wepped in _WeaponPeds)
            {


                if (IsTargeted)
                {
                    GTA.Camera gamecam = new GTA.Camera();
                    GTA.ScriptApi.GetGameCam(gamecam);
                    float rotx, roty, rotz;
                    GTA.ScriptApi.GetCamRot(gamecam, &rotx, &roty, &rotz);
                    GTA.ScriptApi.SetCharHeading(wepped, rotz);
                    target = GTA.World.GetAimCoordinates(70.0F);

                }
                else if (AttachPoint == eAttachPoint.Front_Bumper)
                {
                    wepped.Heading = WeaponVehicle.Heading;
                }
                else if (AttachPoint == eAttachPoint.Back_Bumper)
                {
                    wepped.Heading = WeaponVehicle.Heading - 180.0F;
                }
                else if (AttachPoint == eAttachPoint.Roof)
                {
                    wepped.Heading = WeaponVehicle.Heading;
                }



                GTA.ScriptApi.ClearCharLastDamageEntity(wepped); // test, not needed
                GTA.ScriptApi.SetAmmoInClip(wepped, WeaponType, 999); // doing this every shot stopes them from having to reload, but also causes rocket launcher to fire as fast as a fucking uzi :(
                GTA.ScriptApi.TaskAimGunAtCoord(wepped, target.X, target.Y, target.Z, 1200000);
                GTA.ScriptApi.FirePedWeapon(wepped, target.X, target.Y, target.Z);
            }
            return true;
        }

        public void Detach()
        {
            foreach (GTA.Ped wepped in _WeaponPeds)
            {
                if (wepped == null) continue;
                if (GTA.Ped.Exists(wepped))
                {
                    GTA.ScriptApi.DetachPed(wepped, true);
                    //GTA.ScriptApi.MarkCharAsNoLongerNeeded(wepped);
                    GTA.ScriptApi.DeleteChar(wepped);
                }
            }
            _WeaponPeds.Clear();

            foreach (GTA.GameObject wepobj in _WeaponObjects)
            {
                if (wepobj == null) continue;
                if (GTA.GameObject.Exists(wepobj))
                {
                    GTA.ScriptApi.SetObjectVisible(wepobj, false);
                    GTA.ScriptApi.DetachObject(wepobj, true);
                    //GTA.ScriptApi.MarkObjectAsNoLongerNeeded(wepobj);
                    GTA.ScriptApi.DeleteObject(wepobj);
                }
            }
            _WeaponObjects.Clear();
            if (GTA.GameObject.Exists(_WeaponTarget))
            {
                GTA.ScriptApi.SetObjectVisible(_WeaponTarget, false);
                GTA.ScriptApi.DetachObject(_WeaponTarget, true);
                //GTA.ScriptApi.MarkObjectAsNoLongerNeeded(_WeaponTarget);
                GTA.ScriptApi.DeleteObject(_WeaponTarget);
            }
            Log.Message("Vehicle Weapons Removed.");
            WeaponVehicle = null;
            Mode = eMode.Idle;
            //if (AttachPoint == eAttachPoint.Front_Bumper) Log.Debug("VehicleWeapon.Detach() done");
        }

        public void CleanUp()
        {
            Log.Debug("VehicleWeapon.CleanUp()");
            if (isAttached) Detach();
            Log.Debug("VehicleWeapon.CleanUp() Done");
        }
    }
}




/*


            
CJ_PROP_AK47 	 2155452301 	 0x8079978D
CJ_PROP_EAGLE 	2539376874 	0x975BD0EA
CJ_PROP_GLOCK 	443141696 	0x1A69CE40
CJ_PROP_GRENADE 	1343754678 	0x501811B6
CJ_PROP_KNIFE 	2636807928 	0x9D2A7EF8
CJ_PROP_M4 	61597377 	0x03ABE6C1
CJ_PROP_Molotov 	2245570494 	0x85D8AFBE
CJ_PROP_MP5 	1350491501 	0x507EDD6D
CJ_PROP_PSG1 	1941123364 	0x73B33124
CJ_PROP_pumpshot 	4035356787 	0xF086A873
CJ_PROP_RIFLE 	4265755143 	0xFE424207
CJ_PROP_RPG 	1469285540 	0x579384A4
CJ_PROP_Shotgun 	1015062504 	0x3C809FE8
CJ_PROP_UZI 	4196999265 	0xFA292061 
 *





            GTA.ScriptApi.SetCharRelationship(_WeaponPed1, 1, 0);
            GTA.ScriptApi.SetCharRelationship(_WeaponPed1, 1, 1);
            GTA.ScriptApi.SetCharRelationship(_WeaponPed1, 1, 2);
            GTA.ScriptApi.SetCharRelationship(_WeaponPed1, 1, 3);
            GTA.ScriptApi.SetCharRelationship(_WeaponPed1, 1, 4);
            GTA.ScriptApi.SetCharRelationship(_WeaponPed1, 1, 5);
            GTA.ScriptApi.SetCharRelationship(_WeaponPed1, 1, 6);
            GTA.ScriptApi.SetCharRelationship(_WeaponPed1, 1, 7);
            
            //GTA.ScriptApi.SetCharRelationshipGroup(_WeaponPed1, 0); 
            //GTA.ScriptApi.SetCharVisible(_WeaponPed1, false);
            //GTA.ScriptApi.SetCharKeepTask(_WeaponPed1, true);
            //GTA.ScriptApi.TaskAimGunAtCoord(_WeaponPed1, target.X, target.Y, target.Z, 1000000);
            //GTA.ScriptApi.SetCharKeepTask(_WeaponPed1, true);
            //GTA.ScriptApi.FreezeCharPositionAndDontLoadCollision(_WeaponPed1, true);


 * 
 *             //SET_DECISION_MAKER_ATTRIBUTE_CAN_CHANGE_TARGET(L[1002], 0);
    // CREATE_DUMMY_CHAR
 * 
 * GET_WEAPONTYPE_MODEL
 * 
 * // SELECT_WEAPONS_FOR_VEHICLE - prolly chnages ped weapon to uzi
 * 
 * 
 *  BLOCK_CHAR_AMBIENT_ANIMS(L[672], 1);
 *  
 *  SWITCH_PED_TO_ANIMATED(L[673], 1);
 * 
   SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(L[672], 1);
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(L[673], 1);
SET_BLOCKING_OF_NON_TEMPORARY_EVENTS(L[674], 1);


*/